/**
 * PreviewWidget module
 */

import React from 'react';
import Text from './Text';
import Graph from './Graph';
import Picture from './Picture';
import Video from './Video';
import Draw from './Draw';
import Music from './Music';
import Threed from './Threed';
import RedBag from './RedBag';
import Download from './Download';
import Link from './Link';
import Extend from './Extend';
import Lookers from './Lookers';
import HopeBank from './HopeBank';
// 页面中使用到的常量
import consts from '../../../../utils/consts';
import tool from '../../../../utils/tool';

class PreviewWidget extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            animationStyle: {}, // 动画样式
            index: 0,
            animationName: '',
            baseStyle: {},
        };
    }
    initElements() {
        // 初始化需要预览组件的dom元素
        this.elements = {
            widget: $('#preview-wgt-id-' + this.widget.id),
            canvas: $('.editor-canvas'),
        };
    }
    initPosition() {
        let widget = this.props.widget;
        this.position = tool.getPosition(widget, this);
    }
    centerOffsetToBorderOffset(dimensions, offsets) {
        let transform = this.props.transform;
        return {
            left: transform.offset_x + offsets.x - dimensions.width / 2 - 0.5,
            top: transform.offset_y - offsets.y - dimensions.height / 2,
        };
    }
    getPosition() {
        let widget = this.props.widget;
        let width = widget.width;
        let height = widget.height;
        let dimensions = {
            width: Math.max(width, 1),
            height: Math.max(height, 1),
        };
        let coords = this.centerOffsetToBorderOffset(dimensions, {
            x: widget.offset_x || 0,
            y: widget.offset_y || 0,
        });

        return {
            left: Math.round(coords.left),
            top: Math.round(coords.top),
            width: Math.round(dimensions.width),
            height: Math.round(dimensions.height),
            zIndex: Math.round((widget.offset_z) * 100),
            fontSize: tool.getFontSizeByWidth(dimensions.height),
        };
    }
    filterTimelines(timelines) {
        let tls = [];
        timelines.forEach((timeline) =>  {
                let tb = timeline.triggered_by || [];
                if (!tb.length) {
                        tls.push(timeline);
                    }
            });
        return tls;
    }
    getAnimations() {
        let widget = this.props.widget;
        let singleWidget = this.props.singleWidget;
        let singleTimeline = this.props.singleTimeline;
        // 如果是单个元件预览，则只获取当前编辑的动效
        if (singleWidget) {
            // 单个预览结束时间
            var single = singleTimeline.an_types[0];
            // 是否是循环
            if (parseInt(single.loop_type)) {
                if (parseInt(single.repeat_count_type)) {
                    this.repeat =
                        single.loop_type == 1 ?
                            single.repeat_count * 1000 :
                                single.repeat_count * 2000;
                } else {
                    this.repeat = 60000;
                }
            }

            this.repeat = this.repeat ? this.repeat : 1000;
            storage.data.max_time = (singleTimeline.end_time - singleTimeline.start_time) * this.repeat;

            return [singleTimeline];
        }

        let animations = dataProvider.timelines[widget.id] || [];
        let selectedTimeline = storage.data.selectedTimeline;

        if (animations.length) {
            animations = this.filterTimelines(animations);
        } else {
            animations = this.addDefaultAnTypes();
        }

        for (let i = 0; i < animations.length; i++) {
            var single = animations[i];
            if (selectedTimeline && selectedTimeline.an_types[0]) {
                if (single.id == selectedTimeline.id) {
                    single = animations[i] = selectedTimeline;
                }
            }
            if (parseInt(single.an_types[0].loop_type)) {
                if (parseInt(single.an_types[0].repeat_count_type)) {
                    this.repeat =
                        single.an_types[0].loop_type == 1 ?
                            single.an_types[0].repeat_count * 1000 :
                                single.an_types[0].repeat_count * 2000;
                } else {
                    this.repeat = 60000;
                }
            }
            if (single.end_time > storage.data.max_end_time) {
                storage.data.max_end_time = single.end_time;
            }
        }

        // 是否是循环
        if (single && parseInt(single.loop_type)) {
            if (parseInt(single.repeat_count_type)) {
                this.repeat = single.loop_type == 1 ?
                    single.repeat_count *
                        1000 :
                            single.repeat_count * 500;
            } else {
                this.repeat = 10000;
            }
        }
        this.repeat = this.repeat ? this.repeat : 1000;
        // 预览结束时间为最长的动效结束时间
        storage.data.max_time =
            storage.data.max_time > storage.data.max_end_time * this.repeat ?
                storage.data.max_time :
                    storage.data.max_end_time * this.repeat;
        return animations;
    }
    addDefaultAnTypes() {
        let widget = this.props.widget;
        let animations = [];
        if (widget.type == consts.WIDGET_TYPE.THREED) {
            animations.push({
                start_time: 0,
                end_time: 1,
                an_types: [{
                    an_type: consts.AN_TYPE.BOUNCE,
                    direction: consts.AN_DIRECTION.TOP_TO_BOTTOM,
                }],
            });
        } else {
            animations.push({
                start_time: 0,
                end_time: 1,
                an_types: [{
                    an_type: consts.AN_TYPE.FADE_IN,
                }],
            });
        }
        return animations;
    }
    // 点击canvas关闭预览
    closePreview() {
        let root = this.props.root;
        let showPreview = root.state.preview.showPreview;
        // 正在预览
        if (showPreview) {
            root.setState({
                preview: {
                    showPreview: false,
                },
            });
            $('.editor_hidden').css({ 'opacity': 1 });
        }
    }
    bindEvent() {
        let element = this.elements.widget,
            widget = this.props.widget,
            self = this;

        element.bind('webkitAnimationEnd', () =>  {
            let index = self.state.index;
            if (index > self.animations.length - 1) {
                return false;
            }
            index = self.animations.length - 1 > index ? index + 1 : self.animations.length - 1;
            let str = self.state.animationName;
            self.setState({ index });
            self.startAnimation();
        });
        element.bind('webkitAnimationStart', () =>  {
            self.setState({
                baseStyle: {
                    width: widget.width,
                    height: widget.height,
                    opacity: widget.opacity,
                },
            });
        });
        this.elements.canvas.on('click', () =>  {
            self.closePreview();
        });
    }
    // 开始做动画
    startAnimation() {
        let element = this.elements.widget;
        let widget = this.props.widget;
        let singleWidget = this.props.singleWidget;
        let str = '';
        if (widget.pageTween) this.pageTween = new TimelineMax({});
        if (!this.animations.length) return;
        let index = this.state.index;
        var an = this.animations[index],
            start_time = an.start_time || 0,
            end_time = an.end_time || 0,
            tween = an.tween || 0,
            an_types = an.an_types || [],
            delay_time = 0;
        if (index > 0) { // 用于计算动效延迟的时间
            delay_time = this.animations[index - 1].end_time;
        }
        if (!end_time || !an_types.length) {
            return false;
        }
        if (singleWidget) {
            start_time = 0;
            end_time = an.end_time - an.start_time;
        }
        for (let j = 0; j < an_types.length; j++) {
            var an = an_types[j];
            tool.rebuildAnimationStyle(an, widget, this.centerOffsetToBorderOffsetByEditorCanvas);
            str = tool.rebuildAnimationParam(start_time, end_time, tween, an, widget, delay_time);
            this.checkRepeatTime(an, start_time, end_time);// 检查循环是否导致时间线重叠
            this.setState({
                animationStyle: {
                   WebkitAnimation: str,
                   width: widget.width,
                   height: widget.height,
                   position: 'absolute',
                   overflow: 'hidden',
               },
                animationName: str,
            });
        }
    }
    // 检查是否有重复的动画
    checkRepeatTime(an, start_time, end_time) {
        let repeat = an.loop_type > 0 ? an.repeat_count_type ? an.repeat_count : 'infinite' : 1;
        let length = this.animations.length;
        if (repeat > 1) {
            let index = this.state.index;
            let durationTime = (end_time - start_time) * repeat,
                an_end_time = start_time + durationTime;
            for (let i = index + 1; i < length; i++) {
                    var an = this.animations[i],
                        start_time = an.start_time || 0;

                    if (start_time < an_end_time) {
                        this.setState({
                            index: i + 1,
                        });
                    }
                }
        } else if (repeat == 'infinite') {
            this.setState({
                index: length,
            });
        }
    }
    // 画布中心参考坐标(组件属性) 转换为 画布顶部参考坐标(实际显示)
    centerOffsetToBorderOffsetByEditorCanvas(xo, yo, dimensions) {
        let transform = this.props.transform;
        let widget = this.props.widget;
        return {
//            left: Math.round(transform.offset_x + xo - dimensions.width / 2),//tweenMax使用的路径坐标
//            top: Math.round(transform.offset_y - yo - dimensions.height / 2),
            left: xo - widget.offset_x,
            top: widget.offset_y - yo,
        };
    }
    componentWillMount() {
        function complateTweens() {
            for (let i = this.completeTweenBacks.length - 1; i >= 0; i--) {
                let cb = this.completeTweenBacks[i];
                cb && cb();
            }
        }

        let widget = this.props.widget;

        this.repeat = 0;
        this.max_time = 0;
        this.max_end_time = 0;
        this.pageTween = new TimelineMax({
            onComplete: complateTweens.bind(this),
        });
        this.completeTweenBacks = [];

        // 获取画布缩放比例
        this.scale = zoomProvider.scale();
        this.widget = this.props.widget;
        this.transform = this.props.transform;
        this.isVectorWidget = consts.VECTOR_WIDGETS.indexOf(widget.type) > -1;

        this.position = this.getPosition();
        this.animations = this.getAnimations();
        this.setState({
            baseStyle: {
                width: widget.width,
                height: widget.height,
                opacity: 0,
            },
        });
    }
    componentDidMount() {
        let root = this.props.root;

        this.initElements();
        this.bindEvent();

        // 开始动效播放
        setTimeout(() => {
            this.startAnimation();
        }, 10);
        // 恢复动效层，结束动画
        setTimeout(() => {
             this.closePreview();
             storage.data.max_time = 0;
             storage.data.max_end_time =0;
         }, storage.data.max_time);
    }
    render() {
        this.initPosition();
        let renderNode = '', 
innerNode = '';
        let widget = this.props.widget;
        if (typeof widget.visible === 'undefined') {
            widget.visible = true;
        }
        let rotate_y = -widget.rotate_y;
        let nStyle = {
            display: widget.visible ? 'block' : 'none',
            transform: `rotateX(${  widget.rotate_x  }deg)` + `rotateY(${  rotate_y  }deg)` + `rotateZ(${  widget.rotate_z  }deg)`,
        };
        let position = $.extend(true, nStyle, this.position);

        let isPreview = true;
        let isVectorWidget = consts.VECTOR_WIDGETS.indexOf(widget.type) != -1;
        if (isVectorWidget) {
            if (widget.type === consts.WIDGET_TYPE.TEXT) innerNode = <Text widget={widget} preview={isPreview} root={this.props.root}  />;
            if (widget.type === consts.WIDGET_TYPE.GRAPH) innerNode = <Graph widget={widget} preview={isPreview} />;
            if (widget.type === consts.WIDGET_TYPE.REDBAG) innerNode = <RedBag widget={widget} preview={isPreview} />;
            renderNode =
              (<div className="render-widget" style={this.state.baseStyle}>
                    {innerNode}
                </div>);
        } else {
            switch (parseInt(widget.type)) {
            case consts.WIDGET_TYPE.CALLME:
            case consts.WIDGET_TYPE.GEO:
            case consts.WIDGET_TYPE.NEARBY:
            case consts.WIDGET_TYPE.FORM:
                innerNode = <Draw widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.ALBUM:
            case consts.WIDGET_TYPE.PICTURE:
                innerNode = <Picture widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.VIDEO:
                innerNode = <Video widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.MUSIC:
                innerNode = <Music widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.THREED:
                innerNode = <Threed widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.APP_DOWNLOAD:
                innerNode = <Download widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.LINK:
                innerNode = <Link widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.EXTEND:
                innerNode = <Extend widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.LOOKERS:
                innerNode = <Lookers widget={widget} preview={isPreview} />;
                break;
            case consts.WIDGET_TYPE.HOPEBANK:
                innerNode = <HopeBank widget={widget} preview={isPreview} />;
                break;
            }
            renderNode =
              (<div>
                    <del className="prevent-interaction">
                    </del>
                    <div className="render-widget" style={this.state.baseStyle}>
                        {innerNode}
                    </div>
                </div>);
        }
        return (
          <figure id={'preview-wgt-id-' + widget.id} data-id={widget.id} style={position} className={'btg-widget wgt-action-' + widget.type}>
              <div style={this.state.animationStyle}>
                  {renderNode}
                </div>
            </figure>
        );
    }
}

module.exports = PreviewWidget;
